import { klona } from 'klona/json';
import { getCache, setCache, clearCache } from './storage';
import { watch } from 'vue';

/**
 * 重置插件
 *
 * @param context 上下文
 */
export function setupResetStore(context) {
  const { $state, $patch } = context.store;
  const resetEnable = context.options?.resetEnable || false;

  if (resetEnable === true) {
    const defineStore = klona($state); // 拷贝
    context.store.$reset = () => {
      $patch(defineStore);
    };
  }
}

/**
 * 缓存插件
 *
 * @param {Object} context 插件上下文
 *
 * @example
 * defineStore 配置
 * store.options = { enable: true, key: 'app_cache', picks: ['store_key'] }
 * store.options.enable = true 启用缓存
 * store.options.key = 'cacheKey' -- [可选] 缓存key 默认为 store.name
 * store.options.picks = ['store_key1', 'store_key2'] -- [可选] 缓存字段, 默认为全部字段
 */
export function setupStorageStore(context) {
  const { $id, $patch } = context.store;
  const { enable = false, key: code, picks = [], aloneFields = false } = context.options?.storage || {};

  const CACHE_KEY = code || $id.replaceAll('-', '_');

  /**
   * 获取字段
   *
   * @returns {Array}
   */
  const getFields = () => {
    let fields = Object.keys(context.store.$state);
    if (Array.isArray(picks) && picks.length) {
      fields = fields.filter((v) => picks.includes(v));
    }
    return fields;
  };

  /**
   * 注入缓存数据
   */
  const handleInjectData = () => {
    if (aloneFields === false) {
      const state = getCache(CACHE_KEY);
      return state && $patch(state);
    }

    const state = {};
    getFields().forEach((key) => {
      const data = getCache(`${CACHE_KEY}_${key}`);
      if (data) {
        state[key] = data;
      }
    });
    Object.keys(state).length && $patch(state);
  };

  /**
   * 更新缓存
   */
  const handleUpdateCache = async () => {
    let state = klona(context.store.$state);

    if (Array.isArray(picks) && picks.length) {
      const data = Object.entries(state).filter(([key]) => picks.includes(key));
      state = Object.fromEntries(data);
    }

    if (aloneFields === false) {
      return setCache(CACHE_KEY, state);
    }
    getFields().forEach((key) => setCache(`${CACHE_KEY}_${key}`, state[key] ?? null));
  };

  const handleClearCache = () => {
    if (aloneFields === false) {
      return setTimeout(() => clearCache(CACHE_KEY), 100);
    }
    setTimeout(() => {
      const fields = getFields();
      fields.forEach((key) => clearCache(`${CACHE_KEY}_${key}`));
    }, 100);
  };

  /**
   * 监听数据变化
   */
  const onWatchUpdate = () => {
    if (Array.isArray(picks) && picks.length) {
      // 监听指定字段变化
      const fields = getFields();
      watch(() => fields.map((v) => context.store.$state[v]), handleUpdateCache, { deep: true });
    } else {
      // 监听全部数据变化
      watch(context.store.$state, handleUpdateCache, { deep: true });
    }
  };

  if (enable) {
    handleInjectData();
    onWatchUpdate();
    context.store.$clearCache = handleClearCache;
  }
}
